<?php

namespace app\modules\api\controllers;

use Yii;
use yii\web\Controller;
use yii\web\Response;
use app\modules\api\helper\Error;
use app\modules\api\exception\BaseException;

/**
 * 接口方法基类控制器
 */
class BaseController extends Controller
{
    /**
     * 初始化方法：该模块下所有方法返回 `json` 数据
     */
    public function init()
    {
        Yii::$app->response->format = Response::FORMAT_JSON;
        set_exception_handler(function ($e) {
            $extra = $this->_getExtra($e);
            $code = ($e instanceof BaseException) ? $e->getCode() : Error::INTERNAL;
            Yii::$app->response->content = json_encode($this->prepData($code, $extra));
            Yii::$app->response->send();
        });
    }
    /**
     * 获取异常详细信息
     * @param  \Execption $e 一场对象
     * @return array    信息
     */
    private function _getExtra($e)
    {
        $extra = YII_DEBUG ? [
            'line' => $e->getLine(),
            'file' => $e->getFile(),
            'msg'  => $e->getMessage(),
        ] : [];
        $trace = array_slice($e->getTrace(), 1);
        foreach ($trace as &$info) {
            $this->_exportArgs($info);
        }
        $extra['trace'] = $trace;
        return $extra;
    }
    /**
     * 处理 trace 参数列表
     * @param  mixed &$args 参数列表
     * @return mixed        处理结果
     */
    private function _exportArgs(&$args)
    {
        foreach ($args as &$arg) {
            if (is_array($arg)) {
                $this->_exportArgs($arg);
            } else {
                $arg = is_object($arg) ? get_class($arg) : $arg;
            }
        }
        return $args;
    }
    /**
     * 格式化返回数据方法，用户方法中只需返回结果**数组**
     * @return array         返回前端的数据
     */
    public function afterAction($action, $data)
    {
        return $this->prepData($data);
    }
    /**
     * 准备返回数据
     * @param array $data 返回数据
     */
    protected function prepData($data, $extra = '')
    {
        $ret = [
            'code' => Error::OK,
            'message'  => Error::msg(Error::OK)
        ];
        if (is_numeric($data) and $msg = Error::msg((int)$data)) {
            $ret['code'] = (int)$data;
            $ret['message'] = $msg;
        } else {
            $ret['data'] = $data;
        }
        if (!empty($extra)) {
            $ret['extra'] = $extra;
        }
        return $ret;
    }
}
